package com.hongawen.unsafe;

import lombok.SneakyThrows;

/**
 * 多线程同时读写共享变量时，会造成逻辑错误，因此需要通过synchronized同步；
 *
 * 同步的本质就是给指定对象加锁，加锁后才能继续执行后续代码；
 *
 * 注意加锁对象必须是同一个实例；
 *
 * 对JVM定义的单个原子操作不需要同步。
 *
 * 不需要synchronized的操作
 * 基本类型（long和double除外）赋值，例如：int n = m；
 * 引用类型赋值，例如：List<String> list = anotherList。
 * long和double是64位数据，JVM没有明确规定64位赋值操作是不是一个原子操作，不过在x64平台的JVM是把long和double的赋值作为原子操作实现的。
 * @author hongawen
 * @version 1.0.0
 * @date 2021年09月01日 14:43
 */
public class Main {
    public static void main(String[] args) throws Exception {
        AddThread add = new AddThread();
        DecThread dec = new DecThread();
        add.start();
        dec.start();
        add.join();
        dec.join();
        System.out.println(Counter.count);
    }
}

class Counter {
    public static int count = 0;
}

class AddThread extends Thread {

    @SneakyThrows
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            synchronized (Counter.class) {
                Counter.count += 1;
            }
        }
    }
}

class DecThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            synchronized (Counter.class) {
                Counter.count -= 1;
            }
        }
    }
}